using System;
using System.Collections.Generic;
using System.Text;
using Umdf.SideShow;
using Umdf.SideShow.PocketPC;
using System.Windows.Forms;
using Umdf.SideShow.Scf.Events;
using Umdf.SideShow.Scf.ObjectModel;
using Umdf.SideShow.Contents;
using System.Drawing;

namespace SideShowClient
{
    public class ScfNavigator
    {
        private SideShowApplication _application;
        private SideShowEndpoint _endPoint;
        private ICallbackChannel _channel;
        private Umdf.SideShow.Scf.Contents.ScfContent _currentPage;
        private Umdf.SideShow.Scf.Contents.ScfContent _previousPage;
        private Control _container;
        private Dictionary<Umdf.SideShow.Scf.Contents.ScfContent, ScfUserControl> _pages;
        private Stack<Umdf.SideShow.Scf.Contents.ScfContent> _backStack;

        public ScfNavigator(Control container, SideShowApplication app, ICallbackChannel channel)
        {
            _backStack = new Stack<Umdf.SideShow.Scf.Contents.ScfContent>();
            _pages = new Dictionary<Umdf.SideShow.Scf.Contents.ScfContent, ScfUserControl>();
            _container = container;
            _application = app;
            _endPoint = app.Endpoints[SideShowEndpoint.ScfFormatId];
            _endPoint.ContentAdded += new EventHandler<ContentEventArgs>(EndPointContentAdded);
            _channel = channel;
            Navigate(1);
        }

        private void EndPointContentAdded(object sender, ContentEventArgs e)
        {
            if (e.Content.Id == _currentPage.Id)
            {
                _container.Invoke(new Action<Umdf.SideShow.Scf.Contents.ScfContent>(Update), (Umdf.SideShow.Scf.Contents.ScfContent)e.Content);
            }
        }

        private void Update(Umdf.SideShow.Scf.Contents.ScfContent content)
        {
            ScfUserControl ctrl = (ScfUserControl)_container.Controls[0];
            ctrl.ScfObject = content.ScfDocument.Body;
        }

        public Image GetImage(uint id)
        {
            ImageContent ic = (ImageContent) _endPoint.GetContent(id);
            return ic.Image;
        }

        public void Back()
        {
            if(_backStack.Count > 0)
            {
                _previousPage = _currentPage;
                _currentPage = _backStack.Pop();
                uint prevId = _previousPage == null ? 0 : _previousPage.Id;
                ScfNavigationEvent e = new ScfNavigationEvent(_application.Id, _endPoint.Id, prevId, _currentPage.Id, Umdf.SideShow.Scf.ScfButton.Back);
                _channel.PostEvent(e);
                UserControl ctrl = GetPage(_currentPage);
                _container.Controls.Clear();
                _container.Controls.Add(ctrl);
            }
        }

        public void Navigate(uint target)
        {
            Navigate(target, Umdf.SideShow.Scf.ScfButton.Select);
        }

        public void Navigate(uint target, Umdf.SideShow.Scf.ScfButton btn)
        {
            _previousPage = _currentPage;
            uint prevId = _previousPage == null ? 0 : _previousPage.Id;
            Umdf.SideShow.Scf.Contents.ScfContent t = (Umdf.SideShow.Scf.Contents.ScfContent)_endPoint.GetContent(target);
            _currentPage = t ?? _currentPage;
            ScfNavigationEvent e = new ScfNavigationEvent(_application.Id, _endPoint.Id, prevId, target, btn);
            _channel.PostEvent(e);
            if (_previousPage != null)
            {
                _backStack.Push(_previousPage);
            }
            UserControl ctrl = GetPage(_currentPage);
            _container.Controls.Clear();
            _container.Controls.Add(ctrl);
        }

        

        public void Navigate(ScfMenuItem menuItem)
        {
            _previousPage = _currentPage;
            uint prevId = _previousPage == null ? 0 : _previousPage.Id;
            Umdf.SideShow.Scf.Contents.ScfContent t = (Umdf.SideShow.Scf.Contents.ScfContent)_endPoint.GetContent(menuItem.TargetId);
            _currentPage = t ?? _currentPage;
            ScfMenuActionEvent e = new ScfMenuActionEvent(_application.Id, _endPoint.Id, prevId, menuItem.TargetId, Umdf.SideShow.Scf.ScfButton.Select, menuItem.Id); 
            _channel.PostEvent(e);
            if (_previousPage != null)
            {
                _backStack.Push(_previousPage);
            }
            UserControl ctrl = GetPage(_currentPage);
            _container.Controls.Clear();
            _container.Controls.Add(ctrl);
        }

        public void Navigate(ScfButton btn)
        {
            _previousPage = _currentPage;
            uint prevId = _previousPage == null ? 0 : _previousPage.Id;
            Umdf.SideShow.Scf.Contents.ScfContent t = (Umdf.SideShow.Scf.Contents.ScfContent)_endPoint.GetContent(btn.TargetId);
            _currentPage = t ?? _currentPage;
            Umdf.SideShow.Scf.ScfButton key = GetKey(btn.Key);
            if (btn.Key == ScfButtonKey.Home)
            {
                _currentPage = (Umdf.SideShow.Scf.Contents.ScfContent)_endPoint.GetContent(1);
            }
            ScfNavigationEvent e = new ScfNavigationEvent(_application.Id, _endPoint.Id, prevId, btn.TargetId, key);
            _channel.PostEvent(e);
            if (_previousPage != null)
            {
                _backStack.Push(_previousPage);
            }
            UserControl ctrl = GetPage(_currentPage);
            _container.Controls.Clear();
            _container.Controls.Add(ctrl);
        }

        private Umdf.SideShow.Scf.ScfButton GetKey(ScfButtonKey key)
        {
            switch (key)
            {
                case ScfButtonKey.Back:
                    return Umdf.SideShow.Scf.ScfButton.Back;
                case ScfButtonKey.Enter:
                    return Umdf.SideShow.Scf.ScfButton.Select;
                case ScfButtonKey.Home:
                    return Umdf.SideShow.Scf.ScfButton.Select;
                case ScfButtonKey.Left:
                    return Umdf.SideShow.Scf.ScfButton.Left;
                case ScfButtonKey.Right:
                    return Umdf.SideShow.Scf.ScfButton.Right;
            }
            throw new ArgumentException();
        }

        private UserControl GetPage(Umdf.SideShow.Scf.Contents.ScfContent content)
        {
            ScfUserControl ctrl = null;
            if (content.ScfDocument.Body is ScfMenu)
            {
                ctrl = new ScfMenuControl(this);

            }
            if (ctrl != null)
            {
                ctrl.Dock = DockStyle.Fill;
                ctrl.ScfObject = content.ScfDocument.Body;
                //_pages.Add(content, ctrl);
            }
            return ctrl;
        }
    }
}
